#include "pack.h"

//客户端的封包函数
int Client_pack(unsigned char* send_cmd,char* arg,enum CMD_NO cmd)
{   
    printf("arg=%s\n",arg);
    int i = 0;
    int arg_1_len = 0;
    int pkg_len = 0;
    enum CMD_NO cmdnum;
    arg_1_len = strlen(arg);//命令参数的长度
    printf("arg_len=%d\n",arg_1_len);
    switch(cmd)
    {
        case FTP_CMD_LS:
        {
            i = 0;
            pkg_len = 8;//数据包的总长度  
            cmdnum = FTP_CMD_LS;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 数据包的长度
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_LS >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_LS >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_LS >> 24) & 0xff;
            send_cmd[i++] = 0xc0;//包尾
            break;
        }
        case FTP_CMD_GET:
        {
            i = 0;
            arg_1_len = strlen(arg);//命令参数的长度
            pkg_len = 12 + arg_1_len;
            cmdnum = FTP_CMD_GET;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_GET & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_GET >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_GET >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_GET >> 24) & 0xff;
            send_cmd[i++] = arg_1_len & 0xff;//小端模式存放，先存低字节 命令参数
            send_cmd[i++] = (arg_1_len >> 8) & 0xff;
            send_cmd[i++] = (arg_1_len >> 16) & 0xff;
            send_cmd[i++] = (arg_1_len >> 24) & 0xff;
            strncpy(send_cmd+i,arg,arg_1_len);//命令参数字符串拷贝
            i+=arg_1_len;
            send_cmd[i++] = 0xc0;//包尾
        
        break;
        }
        case FTP_CMD_PUT:
        {
            i = 0;
            arg_1_len = strlen(arg);//命令参数的长度
            printf("arg_len=%d\n",arg_1_len);
            pkg_len = 12 + arg_1_len;
            cmdnum = FTP_CMD_PUT;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_PUT & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_PUT >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_PUT >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_PUT >> 24) & 0xff;
            send_cmd[i++] = arg_1_len & 0xff;//小端模式存放，先存低字节 命令参数
            send_cmd[i++] = (arg_1_len >> 8) & 0xff;
            send_cmd[i++] = (arg_1_len >> 16) & 0xff;
            send_cmd[i++] = (arg_1_len >> 24) & 0xff;
            strncpy(send_cmd+i,arg,arg_1_len);//命令参数字符串拷贝
            i+=arg_1_len;
            send_cmd[i++] = 0xc0;//包尾
            char write_buf[5555]={0};
            int write_len =send_cmd[9]|(send_cmd[10]<<8)|(send_cmd[11]<<16)|(send_cmd[12]<<24);
            printf("write_len:%d\n",write_len);
            strncpy(write_buf,send_cmd + 13,write_len);
            printf("writebyf:%s\n",write_buf);
            break;
        }
        case FTP_CMD_BYE:
        {
            i = 0;
            pkg_len = 8;//数据包的总长度  
            cmdnum = FTP_CMD_BYE;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 数据包的长度
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_BYE & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_BYE >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_BYE >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_BYE >> 24) & 0xff;
            send_cmd[i++] = 0xc0;//包尾
            break;
        }
        case FTP_CMD_CD:
        {
            //printf("进入到了FTP_CMD_CD的封包处理函数\n");
            //printf("arg:%s\n",arg);
            i = 0;
            arg_1_len = strlen(arg);//命令参数的长度
            pkg_len = 12 + arg_1_len;
            cmdnum = FTP_CMD_CD;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_CD & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_CD >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_CD >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_CD >> 24) & 0xff;
            send_cmd[i++] = arg_1_len & 0xff;//小端模式存放，先存低字节 命令参数
            send_cmd[i++] = (arg_1_len >> 8) & 0xff;
            send_cmd[i++] = (arg_1_len >> 16) & 0xff;
            send_cmd[i++] = (arg_1_len >> 24) & 0xff;
            strncpy(send_cmd+i,arg,arg_1_len);//命令参数字符串拷贝
            i+=arg_1_len;
            send_cmd[i++] = 0xc0;//包尾
            //printf("包内的cmd:%d\n",send_cmd[5]|(send_cmd[6]<<8)|(send_cmd[7]<<16)|(send_cmd[8]<<24));
            break;
            
        }
        case FTP_CMD_PWD:
        {
            i = 0;
            pkg_len = 8;//数据包的总长度  
            cmdnum = FTP_CMD_PWD;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 数据包的长度
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_PWD & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_PWD >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_PWD >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_PWD >> 24) & 0xff;
            send_cmd[i++] = 0xc0;//包尾
            break;
        }
        case FTP_CMD_UNKNOWN:
        {
            i = 0;
            pkg_len = 8;//数据包的总长度  
            cmdnum = FTP_CMD_UNKNOWN;
            send_cmd[i++] = 0xC0;//包头 
            send_cmd[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 数据包的长度
            send_cmd[i++] = (pkg_len >> 8) & 0xff;
            send_cmd[i++] = (pkg_len >> 16) & 0xff;
            send_cmd[i++] = (pkg_len >> 24) & 0xff;
            send_cmd[i++] = FTP_CMD_UNKNOWN & 0xff;//小端模式存放，先存低字节 命令号
            send_cmd[i++] = (FTP_CMD_UNKNOWN >> 8) & 0xff;
            send_cmd[i++] = (FTP_CMD_UNKNOWN >> 16) & 0xff;
            send_cmd[i++] = (FTP_CMD_UNKNOWN >> 24) & 0xff;
            send_cmd[i++] = 0xc0;//包尾
            //printf("unknown cmd number\n");
            break;
        }
        default:
        printf("error cmd number");
        break;
    }

    return i;//表示要传输的数据个数
    
}

//服务器的封包函数
int Server_pack(char* resp,char*filenames,enum CMD_NO cmd)
{
    int x = strlen(filenames);
    int pkg_len = 13+x;
    enum CMD_NO cmdnum = cmd;
    int resp_len = 1+x;
    char result = 1;
    int i = 0;
    switch(cmd)
    {
        case FTP_CMD_LS:
        {
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_LS >> 8) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 16) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            strncpy(resp+i,filenames,x);
            i+=x;
            resp[i++] = 0xc0;
            break;
        }
        case FTP_CMD_GET:
        {
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_LS >> 8) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 16) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            strncpy(resp+i,filenames,x);
            i+=x;
            resp[i++] = 0xc0;
            break;
        }
        case FTP_CMD_PUT:
        {
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_LS >> 8) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 16) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            strncpy(resp+i,filenames,x);
            i+=x;
            resp[i++] = 0xc0;
            break;
        }
        case FTP_CMD_BYE:
        {
            
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_LS >> 8) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 16) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            resp[i++] = 0xc0;
        }
        case FTP_CMD_UNKNOWN:
        {
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_LS & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_LS >> 8) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 16) & 0xff;
            resp[i++] = (FTP_CMD_LS >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            resp[i++] = 0xc0;
        }
        case FTP_CMD_PWD:
        {
            resp[i++] = 0xC0;//包头 
            resp[i++] = pkg_len & 0xff;//小端模式存放，先存低字节 
            resp[i++] = (pkg_len >> 8) & 0xff;
            resp[i++] = (pkg_len >> 16) & 0xff;
            resp[i++] = (pkg_len >> 24) & 0xff;
            resp[i++] = FTP_CMD_PWD & 0xff;//小端模式存放，先存低字节 命令号
            resp[i++] = (FTP_CMD_PWD >> 8) & 0xff;
            resp[i++] = (FTP_CMD_PWD >> 16) & 0xff;
            resp[i++] = (FTP_CMD_PWD >> 24) & 0xff;
            resp[i++] = resp_len & 0xff;//小端模式存放，先存低字节
            resp[i++] = (resp_len >> 8) & 0xff;
            resp[i++] = (resp_len >> 16) & 0xff;
            resp[i++] = (resp_len >> 24) & 0xff;
            resp[i++] = result;
            strncpy(resp+i,filenames,x);
            i+=x;
            resp[i++] = 0xc0;
            break;
        }
        default:
        break;
    }
    return i;

}

//获取当前服务器目录下的所有文件的名字
void get_filename(char* pathname,char* filename)
{
    //1.打开一个目录 
    DIR *dirp = opendir(pathname);
    if(dirp == NULL)
    {
        perror("opendir error");
        return;
    }
    //2.读取一个目录
    struct dirent * dir;
    int i = 0;
    while(dir = readdir(dirp))
    {
        if(dir->d_name[0] == '.')
        {
            continue;
        }
        strncpy(filename+i,dir->d_name,strlen(dir->d_name));
        i += strlen(dir->d_name);
        filename[i++] = ' ';//空格隔开
        //printf("%s ",dir->d_name);//文件的名字
    }
    //3.关闭目录
    closedir(dirp);
}

//服务器端命令是ls的处理函数
void ser_hand_ls(int confd,char* resp,enum CMD_NO cmd)
{
    printf("Serdir:%s\n",Serdir);
    unsigned char filename[4096] = {0};//文件名
    get_filename(Serdir,filename);//获取当前服务器目录下的文件名
    printf("FTP_server filename : %s\n",filename);
    int resp_num = Server_pack(resp,filename,cmd);
    send(confd,(void*)resp,resp_num,0);
}

//服务器端命令是get的处理函数
void ser_hand_get(int confd,char* resp,enum CMD_NO cmd,char* arg)
{
    resp[13]=1;
    struct dirent* dirp=NULL;
    DIR *dir=opendir(Serdir);
    if(dir == NULL)
    {
        perror("opendir failed");
        return ;
    }
    while(dirp=readdir(dir))
    {
        if(!strcmp(dirp->d_name,".")||!strcmp(dirp->d_name,".."))
        {
            continue;
        }
        if(strncmp(dirp->d_name,arg,strlen(arg))==0)//查找当前文件夹是否有需要的文件或目录
        {
            char path[256] = {0};
            sprintf(path,"%s/%s",Serdir,arg);//将其拼装成合法路径可以open
            printf("组装后的路径path:%s\n",path);//列入./serdir/1.txt
            struct stat st;
            stat(path,&st);//文件属性
            if(S_ISREG(st.st_mode))//判断是否文件
            {
                //打开文件
                int fd = open(path,O_RDWR);
                //读写文件
                while(1)
                {
                    unsigned char filename[2000] = {0};//存放文件中读取数据的数组
                    char reply[20] = {0};//发送读的数据接收对方的回复
                    int read_num = read(fd,filename,1024);//读取到的数据的个数
                    printf("filename :%s\n",filename);
                    int resp_num = Server_pack(resp,filename,cmd);
                    send(confd,(void*)resp,resp_num,0);
                    recv(confd,reply,19,0);
                    printf("reply:%s\n",reply);
                    if(read_num < 1024)
                    {
                        break;
                    }
                }
                //关闭文件
                close(fd);
                break;
            }
            else if(S_ISDIR(st.st_mode))//目录文件
            {
                unsigned char filename[2000] = {"目前不能传输目录文件"};//存放文件中读取数据的数组 
                printf("%s\n",filename);
                char reply[20] = {0};//发送读的数据接收对方的回复
                int resp_num = Server_pack(resp,filename,cmd);//服务器打包
                resp[13]=0;
                send(confd,(void*)resp,resp_num,0);
                //recv(confd,reply,19,0);
            }
            break;
        }
       
    }
    if(!dirp)
    {
        printf("没有此文件\n");
        int resp_num=Server_pack(resp,"没有此文件",cmd);
        resp[13]=0;
        send(confd,(void*)resp,resp_num,0);
    }
    closedir(dir);
}
    
//服务器端命令是put的处理函数
void ser_hand_put(int confd,char* resp,enum CMD_NO cmd,char* arg)
{
    char path[256] = {0};
    sprintf(path,"%s/%s",Serdir,arg);
    printf("path:%s\n",path);
    //打开文件
    int fd = open(path,O_RDWR|O_CREAT|O_TRUNC,0777);
    while(1)
    {
        unsigned char filename[2000] = {0};
        char write_buf[1024] = {0};
        int resp_num = Server_pack(resp,"ok",cmd);
        recv(confd,(void*)filename,1999,0);
        send(confd,(void*)resp,resp_num,0);
        int write_len =filename[9]|(filename[10]<<8)|(filename[11]<<16)|(filename[12]<<24);
        printf("write_len:%d\n",write_len);
        strncpy(write_buf,filename + 13,write_len);
        if(strncmp(write_buf,"no",2)==0)
        {
            unlink(path);
            break;
        }
        int write_num = write(fd,write_buf,write_len);
        if(write_num < 1024)
        {
            break;
        }
    }
    printf("Transmit Success\n");
    //关闭文件
    close(fd);

}
//服务器cd处理
void ser_hand_cd(char* arg,char*nserdir,int confd)
{
    int bsu=0;
    if(!strncmp("../",arg,3))
    {
        char path[256] = {0};
        strncpy(Serdir,nserdir,128);
        unsigned char buf10[20]={"ok"};
        send(confd,buf10,strlen(buf10),0);
        //DIR *dirp = opendir("../");
        return;

    }
    //printf("进入了cd命令的处理函数\n");
    if(!strncmp("./serdir",arg,8))
    {
        char path[256] = {0};
        strncpy(Serdir,arg,128);
        unsigned char buf10[20]={"ok"};
        send(confd,buf10,strlen(buf10),0);
        //DIR *dirp = opendir("../");
        return;

    }
    char path[256] = {0};
    memset(nserdir,0,sizeof(nserdir));
    strncpy(nserdir,Serdir,128);//保存之前的目录地址
    printf("%s\n",nserdir);
    sprintf(path,"%s/%s",Serdir,arg);
    printf("path:%s\n",path);
    int flag = 0;
    //1.打开一个目录 
    DIR *dirp = opendir(Serdir);
    if(dirp == NULL)
    {
        perror("opendir error");
        return;
    }
    //2.读取一个目录
    struct dirent * dir;
    int i = 0;
    while(dir = readdir(dirp))
    {
        if(dir->d_name[0] == '.')
        {
            continue;
        }
        if(!strcmp(dir->d_name,arg))
        {
            struct stat st;
            stat(path,&st);
            if(S_ISDIR(st.st_mode))
            {
                unsigned char buf10[20]={"ok"};
                send(confd,buf10,strlen(buf10),0);
                flag = 1;
                bsu=1;
            }
            else
            {
               
                send(confd,"不是目录",strlen("不是目录"),0);
                printf("cd的对象不是目录\n");
                bsu=1;
            }
        }
    }
    if(bsu==0)
    {
        unsigned char buf10[20]={"没有此文件"};
        send(confd,buf10,strlen(buf10),0);
    }
    //3.关闭目录
    closedir(dirp);
    if(flag)
    {
        strncpy(Serdir,path,128);
    }
}

//服务器端命令是bye的处理函数
void ser_hand_bye(int confd,char* resp,enum CMD_NO cmd,struct sockaddr_in client)
{
    char filename[100] = {0};
    int resp_num = Server_pack(resp,filename,cmd);
    send(confd,(void*)resp,resp_num,0);
    printf("%s[port:%d] exit!!!\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
}

void ser_hand_pwd(int confd,char* resp,enum CMD_NO cmd)//服务器获取当前目录地址
{
    printf("Serdir:%s\n",Serdir);
    //unsigned char recv_cmd[2000] = {0};//接收服务器回复的数组
    int resp_num = Server_pack(resp,Serdir,cmd);
    send(confd,(void*)resp,resp_num,0);
}
//服务器端命令是unknown的处理函数
void ser_hand_unknown(int confd,char* resp,enum CMD_NO cmd)
{
    char filename[100] = {0};
    int resp_num = Server_pack(resp,filename,cmd);
    send(confd,(void*)resp,resp_num,0);
    printf("unknown cmd number!!!\n");
}

//客户端命令是ls的处理函数
void clie_hand_ls(int sockfd)
{
    unsigned char recv_cmd[10240] = {0};//接收服务器回复的数组
    char recv_buf[4096] = {0};
    int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
    if(ret == -1)
    {
        perror("recv failed");
        return;
    }
    //服务器发送来的数据长度当中有个发送成功或者失败的状态码，所以在打印发送来的数据的时候应该跳过这个状态码
    int len = recv_cmd[9]|(recv_cmd[10]<<8)|(recv_cmd[11]<<16)|(recv_cmd[12]<<24);
    strncpy(recv_buf,recv_cmd+14,len-1);
    printf("%s\n",recv_buf);//展示服务器发来的数据也就是ls的作用
}

//客户端命令是get的处理函数
int clie_hand_get(int sockfd,char* pathname)
{
    char path[256] = {0};
    sprintf(path,"%s/%s",Cliedir,pathname);
    printf("sprintf path:%s\n",path);
    struct dirent* dirp=NULL;
    DIR *dir=opendir(Cliedir);
    if(dir == NULL)
    {
        perror("opendir failed");
        return -1;
    }
    while(dirp=readdir(dir))//产看自己文件是否是目录文件
    {
        if(!strcmp(dirp->d_name,".")||!strcmp(dirp->d_name,".."))
        {
            continue;
        }
        if(strncmp(dirp->d_name,pathname,strlen(pathname))==0)//查找当前文件夹是否有需要的文件或目录
        {
            struct stat st;
            stat(path,&st);//文件属性
            if(S_ISDIR(st.st_mode))//目录文件
            {
                //unsigned char filename[2000] = {"no"};//存放文件中读取数据的数组 
                printf("当前目录有与get文件冲突目录文件不能传输\n");
                unsigned char recv_cmd[10240] = {0};//接收服务器回复的数组
                int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
                return -1;
            }
            else
            {
                break;
            }
        }
    }  
    //打开文件
    int fd = open(path,O_RDWR|O_CREAT|O_TRUNC,0777);
    if(fd == -1)
    {
        perror("open failed");
        return -1;
    }
    //写文件
    while(1)
    {
        unsigned char recv_cmd[10240] = {0};//接收服务器回复的数组
        char recv_buf[2000] = {0};//存放服务器发送的字符串数据的数组
        int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
        if(ret == -1)
        {
            perror("recv failed");
            return -1;
        }
        if(!recv_cmd[13])
        {
            unlink(path);
            int len = recv_cmd[9]|(recv_cmd[10]<<8)|(recv_cmd[11]<<16)|(recv_cmd[12]<<24);
            strncpy(recv_buf,recv_cmd+14,len-1);
            printf("%s\n",recv_buf);
            return -1;
        }
        //字符串数据的长度
        int len = recv_cmd[9]|(recv_cmd[10]<<8)|(recv_cmd[11]<<16)|(recv_cmd[12]<<24);
        printf("write_len:%d\n",len);
        strncpy(recv_buf,recv_cmd+14,len-1);
        ret = write(fd,recv_buf,len-1);
        send(sockfd,"ok!!!",strlen("ok!!!"),0);
        if(ret < 1024)//规定服务器每次发送1024个字节，如果少于1024，则跳出来
        {
            break;
        }
    }
    //关闭文件
    close(fd);
}

//客户端命令是put的处理函数
void clie_hand_put(int sockfd,char* pathname,enum CMD_NO cmd,unsigned char* send_cmd)
{
    struct dirent* dirp=NULL;
    DIR *dir=opendir(Cliedir);
    if(dir == NULL)
    {
        perror("opendir failed");
        return ;
    }
    while(dirp=readdir(dir))
    {
        if(!strcmp(dirp->d_name,".")||!strcmp(dirp->d_name,".."))
        {
            continue;
        }
        if(strncmp(dirp->d_name,pathname,strlen(pathname))==0)//查找当前文件夹是否有需要的文件或目录
        {
            char path[256] = {0};
            sprintf(path,"%s/%s",Cliedir,pathname);
            struct stat st;
            stat(path,&st);//文件属性
            if(S_ISREG(st.st_mode))//判断是否文件
            {
                //打开文件
                int fd = open(path,O_RDWR);
                //读写文件
                while(1)
                {
                    unsigned char filename[2000] = {0};//存放文件中读取数据的数组
                    char reply[20] = {0};//发送读的数据接收对方的回复
                    int read_num = read(fd,filename,1024);//读取到的数据的个数
                    printf("filename :%s\n",filename);
                    int resp_num = Client_pack(send_cmd,filename,cmd);
                    send(sockfd,(void*)send_cmd,resp_num,0);
                    recv(sockfd,reply,19,0);
                    printf("reply:%s\n",reply);
                    if(read_num < 1024)
                    {
                        break;
                    }
                }
                //关闭文件
                close(fd);
                break;
            }
            else if(S_ISDIR(st.st_mode))//目录文件
            {
                //unsigned char filename[2000] = {"no"};//存放文件中读取数据的数组 
                printf("目前不能传输目录\n");
                char reply[20] = {0};//发送读的数据接收对方的回复
                int resp_num = Client_pack(send_cmd,"no",cmd);//服务器打包
                send(sockfd,send_cmd,resp_num,0);
                recv(sockfd,reply,19,0);
            }
            break;
        }
    }
    if(!dirp)
    {
        char reply[20] = {0};//发送读的数据接收对方的回复
        printf("没有此文件\n");
        int resp_num=Client_pack(send_cmd,"no",cmd);//封包
        send(sockfd,(void*)send_cmd,resp_num,0);
        recv(sockfd,reply,19,0);
    }
    closedir(dir);
}

//客户端是cd
void clie_hand_cd(int sockfd)
{
    unsigned char recv_cmd[15] = {0};//接收服务器回复的数组
    char recv_buf[10] = {0};
    int ret = recv(sockfd,(void*)recv_cmd,15,0);
    if(ret == -1)
    {
        perror("recv failed");
        return;
    }
    //服务器发送来的数据长度当中有个发送成功或者失败的状态码，所以在打印发送来的数据的时候应该跳过这个状态码
    printf("%s\n",recv_cmd);//展示服务器发来的数据也就是cd的作用
}

//客户端命令是bye的处理函数
void clie_hand_bye(int sockfd)
{
    //printf("byebye!!!\n");
    unsigned char recv_cmd[2000] = {0};//接收服务器回复的数组
    //char recv_buf[4096] = {0};
    int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
    if(ret == -1)
    {
        perror("recv failed");
        return ;
    }
    if(recv_cmd[13])
    {
        printf("服务器已经收到了退出命令，正常退出\n");
    }
}

//客户端命令是unknown的处理函数
void clie_hand_unknown(int sockfd)
{
    unsigned char recv_cmd[2000] = {0};//接收服务器回复的数组
    int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
    if(ret == -1)
    {
        perror("recv failed");
        return ;
    }
    if(recv_cmd[13])
    {
        printf("unkonwn cmd number!!!\n");
    } 
}

void clie_hand_pwd(int sockfd)//客户端获取当前文件目录地址
{
    unsigned char recv_cmd[10240] = {0};//接收服务器回复的数组
    char recv_buf[4096] = {0};
    int ret = recv(sockfd,(void*)recv_cmd,sizeof(recv_cmd),0);
    if(ret == -1)
    {
        perror("recv failed");
        return;
    }
    //服务器发送来的数据长度当中有个发送成功或者失败的状态码，所以在打印发送来的数据的时候应该跳过这个状态码
    int len = recv_cmd[9]|(recv_cmd[10]<<8)|(recv_cmd[11]<<16)|(recv_cmd[12]<<24);
    strncpy(recv_buf,recv_cmd+14,len-1);
    printf("当前地址:%s\n",recv_buf);//展示服务器发来的数据也就是pwd的作用
}

void Knag()//框架
{
    printf(" -------------------------------------------------------------------------\n");
    printf(" |          ls: 用来获取服务器目录中的文件信息(文件名)                   |\n");
    printf(" |          get: 用来从服务器中获取指定文件名的文件                      |\n");
    printf(" |          put:  用来上传文件到服务器                                   |\n");
    printf(" |          cd:到达所选目录(以./serdir/test格式输入)                     |\n");
    printf(" |          pwd: 获取当前目录路径                                        |\n");
    printf(" |          byebye: 用来告诉服务器，客户端即将关闭                       |\n");
    printf("---------------------------------------------------------------------------\n");
}